package org.example;

import org.example.Enum.ActionEnum;
import org.example.Enum.Conditions;
import org.example.Enum.PanelState;
import org.example.Events.*;

import java.util.Scanner;

public class Main {
    private static final Integer ERR_MAX_NUMBER = 3;
    private static final String PASSWORD = "1234";

    private static final Integer LOCKED_TIME = 20;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        StateMachine stateMachine = machineConfig();
        Integer err_number = 0;
        String password;
        while(true){
            password = scanner.next();
            if (password.length() != 4){
                stateMachine.execute(ActionEnum.PWD_NOT_EQUAL_4,null);
                continue;
            }
            stateMachine.execute(ActionEnum.PWD_EQUAL_4, null);
            if (password.equals(PASSWORD)){
                stateMachine.execute(ActionEnum.PWD_CORRECT,null);
                break;
            }else {
                if (err_number < ERR_MAX_NUMBER - 1){
                    err_number += 1;
                    stateMachine.execute(ActionEnum.PWD_INCORRECT, Conditions.low_err_number);
                }else{
                    stateMachine.execute(ActionEnum.PWD_INCORRECT, Conditions.arrive_err_max);
                    try {
                        Thread.sleep(LOCKED_TIME * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                    stateMachine.execute(ActionEnum.TIME_IS_UP, null);
                    err_number = 0;
                }
            }
        }

    }

    protected static StateMachine machineConfig(){
        // 初始状态为Reading
        StateMachine stateMachine = new StateMachine(PanelState.READING);
        // 初始状态为Reading下，密码长度小于4，继续保持reading
        stateMachine.addTranslation().source(PanelState.READING).when(ActionEnum.PWD_NOT_EQUAL_4)
                .Condition(null).targets(PanelState.READING).how(new PWDNotEqual4());
        // 初始状态为Reading下，密码长度等于4，进入checking
        stateMachine.addTranslation().source(PanelState.READING).when(ActionEnum.PWD_EQUAL_4)
                .Condition(null).targets(PanelState.CHECKING).how(new PWDLengthEqual4());
        // 初始状态为checking下，密码不对且错误次数没达到最大次数，进入reading重新输入
        stateMachine.addTranslation().source(PanelState.CHECKING).when(ActionEnum.PWD_INCORRECT)
                .Condition(Conditions.low_err_number).targets(PanelState.READING).how(new PWDIncorrect());
        // 初始状态为checking下，密码不对且错误次数达到最大次数，进入Locked
        stateMachine.addTranslation().source(PanelState.CHECKING).when(ActionEnum.PWD_INCORRECT)
                .Condition(Conditions.arrive_err_max).targets(PanelState.LOCKED).how(new ErrMax());
        // 初始状态为checking下，密码正确，进入selecting
        stateMachine.addTranslation().source(PanelState.CHECKING).when(ActionEnum.PWD_CORRECT)
                .Condition(null).targets(PanelState.SELECTING).how(new PWDCorrect());
        // 初始状态为Locked下，计时器未达到最大时间，保持Locked
        stateMachine.addTranslation().source(PanelState.LOCKED).when(ActionEnum.TIME_IS_NOT_UP)
                .Condition(null).targets(PanelState.LOCKED).how(new TimeIsNotUpEvent());
        // 初始状态为Locked下，计时器达到最大时间，进入Reading重新输入
        stateMachine.addTranslation().source(PanelState.LOCKED).when(ActionEnum.TIME_IS_UP)
                .Condition(null).targets(PanelState.READING).how(new TimeIsUpEvent());
        return stateMachine;
    }
}